<!DOCTYPE html>
<html>
<head><title>Javascript test bench</title></head>

<body onload="_testInterface();">

<form id="testData">
   Test the function: <select id="functions"></select>
   <table id="testTable" style="border: 1px;">
      <tr>
         <th> </th>
         <th>Call</th>
         <th>Expected result</th>
         <th>Actual result</th>
      </tr>
   </table>
   <img src="images/add.png" onClick="_addRow();" height="15" /> <br />
   <input type="button" id="go" value="Run test">
</form>

</body>

<script >

// test interface - creates a form to view and edit the tests, then to run them.
var _testData = opener.testData,
    _lastRow, _fname, _numArgs;

function _testInterface() {
   for (var key in window) _addOption(key);
   var elt = document.getElementById('functions');
   _setRows();
}

function _setRows() {
   document.getElementById('testTable').innerHTML = '<tr><td></td><td>Arguments</td><td>Expected result</td><td>Actual result</td></tr>';
   var elt = document.getElementById('functions');
   _fname = elt.options[elt.selectedIndex].text;
   var f = window[_fname];
   _numArgs = f.length;
   var tin = JSON.parse(_testData.in);
   var tout = JSON.parse(_testData.out);
   _lastRow = 0;
   for (var key in tin) _addRow(tin[key],tout[key]);
   document.getElementById('go').onclick = function() {
      _runTest(f);
   };
}

function _addOption(o) {
   if (typeof window[o] =='function' && !_nativeFunction[o]) {
      var opt = document.createElement('option');
      opt.setAttribute('value',o);
      opt.setAttribute('onclick','_setRows()');
      if (o == _testData.call) opt.setAttribute('selected','selected');
      opt.innerHTML = o;
      var sel = document.getElementById('functions');
      sel.appendChild(opt);
   }
}

function _addRow(inVals,outVal) {
   var row, td, inElt;
   if (!inVals) inVals = [];
   row = document.createElement('tr');
   // option to remove
   td = document.createElement('td');
   inElt = document.createElement('img');
   inElt.setAttribute('src',"images/remove.png");
   inElt.setAttribute('height',"15");
   inElt.setAttribute('onClick',"_removeRow(this);");
   td.appendChild(inElt);
   row.appendChild(td);
   // Function to call and arguments
   td = document.createElement('td');
   inElt = document.createElement('span');
   inElt.innerHTML = _fname +'(';
   if (_numArgs == 0) {
      td.appendChild(inElt);
      inElt = document.createElement('span');
   }
   else {
      for (var i=0; i<_numArgs; i++) {
         td.appendChild(inElt);
         inElt = document.createElement('input');
         inElt.setAttribute('type','text');
         inElt.setAttribute('id','in'+_lastRow+'-'+i);
         if (typeof inVals[i] != 'undefined')
            inElt.setAttribute('value',JSON.stringify(inVals[i]));
         td.appendChild(inElt);
         inElt = document.createElement('span');
         inElt.innerHTML = ',';
      }
   }
   inElt.innerHTML = ')';
   td.appendChild(inElt);
   row.appendChild(td);
   // Expected output
   inElt = document.createElement('input');
   inElt.setAttribute('type','text');
   inElt.setAttribute('id','exp'+_lastRow);
   if (typeof outVal != 'undefined')
      inElt.setAttribute('value',outVal); 
   td = document.createElement('td');
   td.appendChild(inElt);
   row.appendChild(td);
   // Actual output
   td = document.createElement('td');
   td.setAttribute('id','act'+_lastRow);
   row.appendChild(td);
   document.getElementById('testTable').appendChild(row);
   _lastRow++;
}

function _removeRow(r) {
    e = r.parentNode.parentNode;
    e.parentNode.removeChild(e);
}

// runTest - apply the test to each input, and make the output
function _runTest(f) {
   var inElt, outElt, expVal, actVal;
   for (var i=0; i<_lastRow; i++) {
      if (document.getElementById('exp'+i)) {
         inVals = [];
         for (var j=0; j<_numArgs; j++) {
            inElt = document.getElementById('in'+i+'-'+j);
            if (inVal = inElt.value) {
               inVals.push(JSON.parse(inVal))
            }
            else
               j = _numArgs;     
         }
         outElt = document.getElementById('act'+i);
         actVal = _oneTest(f,inVals);
         expVal = document.getElementById('exp'+i).value;
         if (expVal) {
            actVal = actVal + '<img src="images/' + ((expVal==actVal)?'tick.gif':'cross.png') + '" />';
         }
         outElt.innerHTML = actVal;
      }
   }
}

function _oneTest(f,inVals) {
   var res;
   try {
      var outVal = f.apply(window,inVals);
      res = JSON.stringify(outVal);
   }
   catch (e) {
      res = e;
   }
   return res;
}

var _nativeFunction = {};
   for(var _token in window){
      if(typeof window[_token] =='function'){
         _nativeFunction[_token] = true;
      }
   }

eval(opener.codeToRun());

</script>

